package resilienceManager.qmul.gemom;
import inl.resilienceManager.qmul.gemom.npTable;
import inl.resilienceManager.qmul.gemom.solution;

import java.lang.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.Vector;

/**
 * the class for the Gbroker
 * save the information for the self capability of Gbroker
 * could get information from database
* @author Peng Jiang, John Bigham, Jiayi Wu ------------QMUL
 * @version 0.1 
 * */


public class Gbroker {
	
	private int Gid=-1;
	
	// the parameter to represent the capability function
	private double pcf=0; 
	
	// the current capability value for the Gbroker
	private double pnow=0;
	
	private int local_time=0;
	
	// the threshold of the capability
	private double pth;
	
//	1 for alive, 0 for not
	private int alive=1;
	private String ip=""; 
	
	
	ArrayList<NSitem> current = new ArrayList<NSitem>();
	LinkedList<Integer> currentItemIDs = new LinkedList<Integer>();
	
	// constructor of the Gbroker
	public Gbroker(int id, double p)
	{
		this.Gid=id;
		this.pcf=p;
	}
	
	public Gbroker(int id, double p, String ip){
		this.Gid=id;
		this.pcf=p;
		this.ip=ip;
	}
	
	// constructor for the ini allocation 
	public Gbroker(int id, double p, double th){
		
		this.Gid=id;
		
		this.pcf=p;
		
		this.pth=th;
	}
	
	public Gbroker(int id, double p, double th, String ip){
		
		this.Gid=id;
		
		this.pcf=p;
		
		this.pth=th;
		this.ip=ip;

	}
	
//	set
	public ArrayList<NSitem> getCurrentItems(){
		return current;
	}
	
	public LinkedList<Integer> getItemIDs(){

		return currentItemIDs; 
	}
	
	public void setCurrentItems(NSitem[] items){
//		current= new ArrayList<NSitem>(Arrays.asList(items));
		current.clear();
		current.addAll(Arrays.asList(items));
		for (NSitem i: current){
			currentItemIDs.add(new Integer(i.getID()));
		}
	}
	
	public void addCurrentItems(NSitem[] items){
		current.addAll(Arrays.asList(items));
	}
	
	// get the ID of the Gbroker
	public int getID()
	{
		return this.Gid;
	}
	
	// get the capability of the Gbroker
	public double getCAP()
	{
		return this.pcf;
	}
	
	public void setCAP(double pcf){
		this.pcf=pcf;
	}
	
	public void setIP(String s){
		this.ip=s;
	}
	
	public String getIP(){
		return this.ip;
	}
	//
	public double getTh(){
		
		return this.pth;
	}
	
	// set the available value of 
	
	public void setNS(double ns, int time)
	{
		if(local_time!=time)
		{
			pnow=pnow-pcf;
			local_time=time;
			pnow=pnow+ns;
		}
		else
		{
			pnow=pnow+ns;
		}
		
	}
	
	// get the current state
	
	public double getState()
	{
		return this.pnow;
	}
	
	// check if could accept this scheme
	// for simplify , the scheme here is used to 
	// calculate the total number of NS
	// for the potential risk when accept the 
	public boolean acceptAll(int vs)
	{
		boolean t=false;
		
		if(vs<30)
		{
			t=true;
		}
		
		return t;
	}
	
//	get capacity of this broker
	double getCap(){
		return pcf*3;
	}
//TODO	current load of this broker
	double getV(){
		return 0;
	}
	
//	TODO is broker alive?
	public int isAlive(){
		return alive;
	}
	public int setAlive(int a){
		alive = a;
		return alive;	
	}
	
	
	// get the risk for the allocation scheme Pr(v>C)
	public double getRisk(double v, int size)
	{
		double risk=0;
		
		// define a function for the risk
		
		
		//risk= size/(pcf*pcf);
	
		double z=(getCap()-size)/Math.sqrt(v);
		
		risk=npTable.find(z);
		
		if(risk> pth)
		{
			return risk;
		}
		else
			return risk;
	}
	public double getRisk(double v, double mean)
	{
// "risk" is P(z>x))
		
		double risk=0;
		
		// define a function for the risk
//		mean == 0, is the case no items (message rates) are carried by this broker, then utility is 1 
		if (mean==0){
			return 0;
		}
		
		//risk= size/(pcf*pcf);
		
		double z=(getCap()-mean)/Math.sqrt(v);
		try{
			risk=npTable.find(z);
		}
		
		catch(Exception e){
			e.printStackTrace();
			System.out.println("v=" +v +", mean="+mean);
			risk=0;
		}
		if(risk> pth)
		{
			return risk;
		}
		else
			return risk;
	}
	

	
	public double getRisk(int size)
	{
		
		
		double risk=0;
		
		
		risk=size/(pcf*pcf);
		
		
		return risk;
		
		
		
	}
	
	
	

	
	//XXX todo, use utility build on risk 
//	get the risk for the ini
	public double getRisk(solution al)
	{
		double risk=0;
		
//		(C-v)/sqrt(var), mean al.size
		double z=(getCap()-al.Size())/Math.sqrt(al.variance());
//		double zz=(pcf*20-al.Rate())/Math.sqrt(al.variance());
//		pr(V-v>C-v)
		risk=npTable.find(z);

		
		return risk;
	}

}
